package com.zshan.clinic.web.netty.handler;

import com.fasterxml.jackson.core.type.TypeReference;
import com.zshan.clinic.common.util.json.JsonUtil;
import com.zshan.clinic.web.netty.enums.ProtocolTypeEnum;
import com.zshan.clinic.web.netty.manager.ChannelManager;
import com.zshan.clinic.web.netty.model.HeartbeatRequest;
import com.zshan.clinic.web.netty.model.HeartbeatResponse;
import com.zshan.clinic.web.netty.model.RegisterRequest;
import com.zshan.clinic.web.netty.model.WsMessage;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class WebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    /**
     * 接收到客户端消息
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame socketFrame) {
        String text = socketFrame.text();
        try {
            String protocolType = JsonUtil.getCode(text);
            WsMessage<String> wsMessage = new WsMessage<>();
            if(!ProtocolTypeEnum.isValue(protocolType)){
                log.info("收到未知协议protocolType:{},text:{}",protocolType,text);
                return;
            }
            if(ProtocolTypeEnum.ONLINE_REQ.getValue().equals(protocolType)){
                handleOnline(ctx,text);
            }else if (ProtocolTypeEnum.HEART_REQ.getValue().equals(protocolType)){
                //心跳请求
                handleHeartbeat(ctx,text);
            }
        } catch (Exception e) {
            System.err.println("解析消息异常：" + e.getMessage() + " 内容：" + text);
        }
    }

    /**
     * 设备上线
     * @param ctx
     * @param text
     */
    public void handleOnline(ChannelHandlerContext ctx, String text) {
        log.info("接收到客户端发送的设备上线请求，通道ID:{},内容:{}",ctx.channel().id(),text);
        WsMessage<RegisterRequest> registerReq = JsonUtil.json2Obj(text, new TypeReference<WsMessage<RegisterRequest>>() {});
        if (registerReq == null || registerReq.getData() == null || registerReq.getData().getClinicId() == null) {
            log.warn("注册请求 clinicId 为空，内容: {}", text);
            return;
        }
        Long clinicId = registerReq.getData().getClinicId();
        ChannelManager.add(clinicId, ctx.channel());
        // 可调用 deviceService.updateOnline(clinicId);
        WsMessage<String> resp = new WsMessage<>();
        resp.setCode(ProtocolTypeEnum.ONLINE_RESP.getValue());
        resp.setMsg("连接成功");
        ctx.channel().writeAndFlush(new TextWebSocketFrame(JsonUtil.obj2Json(resp)));
    }

    public void handleHeartbeat(ChannelHandlerContext ctx, String text) {
        log.info("接收到客户端发送的心跳请求，通道ID:{},内容:{}",ctx.channel().id(),text);
        WsMessage<HeartbeatRequest> heartbeatReq = JsonUtil.json2Obj(text, new TypeReference<WsMessage<HeartbeatRequest>>() {});
        if (heartbeatReq != null && heartbeatReq.getData() != null) {
            String clinicId = heartbeatReq.getData().getClinicId();
            // 可调用 deviceService.updateOnline(clinicId);
        }

        WsMessage<HeartbeatResponse> resp = new WsMessage<>();
        resp.setCode(ProtocolTypeEnum.HEART_RESP.getValue());
        resp.setMsg("心跳响应");
        ctx.channel().writeAndFlush(new TextWebSocketFrame(JsonUtil.obj2Json(resp)));
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        log.info("新客户端连接:{}",ctx.channel().id());
    }


    /**
     * 空闲事件触发（如：心跳超时）
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                //心跳超时
                cleanup(ctx);
            }
        }
    }

    /**
     * 连接断开（包括异常和主动关闭）
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        cleanup(ctx);
    }

    /**
     * 异常处理（如关闭连接）
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.info("WebSocket异常：" + cause.getMessage());
        cleanup(ctx);
    }

    /**
     * 连接关闭以后执行的操作
     * @param ctx
     */
    public void cleanup(ChannelHandlerContext ctx) {
        if(ctx != null){
            Long clinicId = ChannelManager.getClinicId(ctx.channel());
            if (clinicId != null) {
                //TODO 这里可以设备下线
            }
            ChannelManager.remove(ctx.channel());
            ctx.close();
        }
    }
}
